home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- * *
- * Heap walk utility - 12/4/94 by Mark Gamber *
- * *
- ******************************************************************************/
-
- #include "windows.h"
- #include "tlhelp32.h"
-
- // === Function Prototypes ====================================================
- // The program "walking tour"
- LRESULT WINAPI MainWndProc( HWND, UINT, WPARAM, LPARAM ); // Main window
- BOOL WINAPI AboutDlgProc( HWND, UINT, WPARAM, LPARAM ); // Beavis box
- BOOL InitApplication( HINSTANCE, int ); // Register class, start window
- BOOL CreateChildWindows( HWND ); // Create listboxes
- BOOL ResizeChildWindows( HWND ); // Resize listboxe when parent is sized
- BOOL ListProcesses( HWND ); // Walk process list
- BOOL FindModuleByID( DWORD, DWORD, char * ); // Get module name by Process ID
- BOOL ListProcessHeap( HWND, DWORD ); // Walk process's heap
- BOOL WINAPI DataDlgProc( HWND, UINT, WPARAM, LPARAM ); // Contents display
-
- // === Global Variables =======================================================
-
- HINSTANCE hInst; // Application instance
- HWND hMainWnd; // Main window handle
- HFONT hFont; // Font used for listboxes
- HBRUSH hBrush; // Brush used for listboxes
- HWND hLastFocus; // Last listbox to get focus
-
- // === Application Entry Point ================================================
-
- int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmd,
- int nShow )
- {
- MSG msg;
-
- if( ! InitApplication( hInstance, nShow ) ) // If ya can't start it
- return( FALSE ); // ya can't run it
-
- while( GetMessage( &msg, NULL, 0, 0 ) ) // Do that message thang
- {
- if( IsDialogMessage( hMainWnd, &msg ) ) // Makes TAB work on a window
- continue; // to change controls
-
- TranslateMessage( &msg ); // If not some dialog thing, do it
- DispatchMessage( &msg ); // the old fashioned way
- }
-
- DeleteObject( hFont ); // Kill these things on the way out
- DeleteObject( hBrush );
- return( FALSE );
- } // End of WinMain()
-
- // === Main Window Procedure ==================================================
-
- LRESULT WINAPI MainWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
- {
- switch( msg )
- {
- case WM_CREATE:
- if( ! CreateChildWindows( hWnd ) ) // Create child windows or
- return( -1 ); // there's no point in proceeding
- ListProcesses( GetDlgItem( hWnd, 10 ) ); // List processes (hey!)
- hLastFocus = GetDlgItem( hWnd, 10 ); // Process box has focus
- break;
-
-
- case WM_DESTROY:
- PostQuitMessage( 0 ); // Kill app when window is killed
- break;
-
-
- case WM_SIZE: // Resize listboxes when this is sized
- ResizeChildWindows( hWnd );
- break;
-
-
- case WM_CTLCOLORLISTBOX: // Color listbox with focus light blue
- if( hLastFocus == (HWND)lParam ) // Is this listbox same as focus?
- { // If so, color it
- SetBkColor( (HDC)wParam, RGB( 0, 255, 255 ) );
- return( (LRESULT)hBrush );
- }
- break; // Else, let Windows have it's way with it
-
-
- case WM_COMMAND:
- {
- if( HIWORD( wParam ) == LBN_SETFOCUS ) // Set colors on focus change
- {
- if( LOWORD( wParam ) == 10 || LOWORD( wParam ) == 11 )
- {
- hLastFocus = (HWND)lParam; // Save new window with focus
- InvalidateRect( GetDlgItem( hWnd, 10 ), NULL, TRUE ); // Force
- InvalidateRect( GetDlgItem( hWnd, 11 ), NULL, TRUE ); // redraw
- }
- else // If on a header, put onto a data listbox
- SetFocus( GetDlgItem( hWnd, LOWORD( wParam ) + 2 ) );
-
- break;
- }
-
- if( wParam == 100 ) // "Update - Processes" selected
- { // Walk process list
- ListProcesses( GetDlgItem( hWnd, 10 ) );
- SetFocus( GetDlgItem( hWnd, 10 ) ); // Give process box focus
- break;
- }
-
- if( wParam == 101 || // "Update-Heap" or process double-click
- ( HIWORD( wParam ) == LBN_DBLCLK &&
- LOWORD( wParam ) == 10 ) ) // on process listbox
- {
- int iItem;
- DWORD dwProcID;
- // Get current process box selection
- iItem = SendDlgItemMessage( hWnd, 10, LB_GETCURSEL, 0, 0 );
- if( iItem == LB_ERR )
- { // Tell user if no selection
- MessageBox( hWnd, "No Process has been selected!",
- "Heap32", MB_OK | MB_ICONEXCLAMATION );
- break;
- } // Get proc ID stored as item data when walked
- dwProcID = SendDlgItemMessage( hWnd, 10, LB_GETITEMDATA,
- iItem, 0 );
- if( dwProcID ) // If seemingly valid...
- { // Display heap for given process
- ListProcessHeap( GetDlgItem( hWnd, 11 ), dwProcID );
- SetFocus( GetDlgItem( hWnd, 11 ) ); // Heap box gets focus
- }
- break;
- }
- if( wParam == 102 || // Want to display item contents?
- ( HIWORD( wParam ) == LBN_DBLCLK &&
- LOWORD( wParam ) == 11 ) )
- {
- int iItem;
- // Get current heap item
- iItem = SendDlgItemMessage( hWnd, 11, LB_GETCURSEL, 0, 0 );
- if( iItem == LB_ERR ) // Tell user if nothing is selected
- {
- MessageBox( hWnd, "No data item has been selected!",
- "Heap32", MB_OK | MB_ICONEXCLAMATION );
- break;
- }
- // Call display dialog, passing selection
- DialogBoxParam( hInst, MAKEINTRESOURCE( 10001 ), hWnd,
- DataDlgProc, iItem );
- break;
- }
- if( wParam == 200 )
- {
- DestroyWindow( hWnd ); // Die on exit
- break;
- }
- if( wParam == 201 )
- { // The Hokey Pokey is what it's really all about
- DialogBox( hInst, MAKEINTRESOURCE( 10000 ), hWnd,
- AboutDlgProc );
- break;
- }
- break;
- } // End of WM_COMMAND
-
-
- default:
- return( DefWindowProc( hWnd, msg, wParam, lParam ) );
- }
- return( FALSE );
- } // End of MainWndProc()
-
- // === Register classes and Start Top Level Window ============================
-
- BOOL InitApplication( HINSTANCE hInstance, int nShow )
- {
- WNDCLASSEX wc;
-
- wc.cbSize = sizeof(WNDCLASSEX);
- wc.style = 0;
- wc.lpfnWndProc = MainWndProc; // Register class
- wc.lpszClassName = "PEEPS32"; // Hiya Pradeep!
- wc.lpszMenuName = "MainMenu";
- wc.hInstance = hInstance;
- wc.hIcon = LoadImage( hInstance, MAKEINTRESOURCE( 100 ), IMAGE_ICON,
- 32, 32, LR_DEFAULTCOLOR );
- wc.hIconSm = LoadImage( hInstance, MAKEINTRESOURCE( 100 ), IMAGE_ICON,
- 16, 16, LR_DEFAULTCOLOR );
- wc.hCursor = LoadCursor( NULL, IDC_ARROW );
- wc.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1 );
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
-
- if( ! RegisterClassEx( &wc ) )// Quit if register fails
- return( FALSE );
-
- hInst = hInstance; // Create the main window
- hMainWnd = CreateWindow( "PEEPS32", "Heap32", WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, CW_USEDEFAULT,
- 300, 216, NULL, NULL, hInstance, NULL );
- if( ! hMainWnd )
- return( FALSE ); // Fail if main window fails
- // Create focus brush
- hBrush = CreateSolidBrush( RGB( 0, 255, 255 ) ); // killed in WinMain()
-
- ShowWindow( hMainWnd, nShow ); // Display main window and we're set
- UpdateWindow( hMainWnd );
- // Use a small font and
- hFont = CreateFont( -8, 0, 0, 0, FW_NORMAL, 0, 0, 0, 0, 0, 0, 0, 0,
- "MS Sans Serif" );
- // Apply it to all the listboxes
- SendDlgItemMessage( hMainWnd, 8, WM_SETFONT, (WPARAM)hFont, 1 );
- SendDlgItemMessage( hMainWnd, 9, WM_SETFONT, (WPARAM)hFont, 1 );
- SendDlgItemMessage( hMainWnd, 10, WM_SETFONT, (WPARAM)hFont, 1 );
- SendDlgItemMessage( hMainWnd, 11, WM_SETFONT, (WPARAM)hFont, 1 );
- return( TRUE );
- } // End of InitApplication()
-
- // === Create Child Listboxes for the Main Window =============================
-
- BOOL CreateChildWindows( HWND hWnd )
- {
- HWND hNew;
- RECT Rect;
- int iSep[ 3 ];
-
- // Get size of the main window
- GetClientRect( hWnd, &Rect ); // Create a header listbox
- hNew = CreateWindow( "listbox", NULL, WS_CHILD | WS_BORDER | WS_VISIBLE |
- LBS_NOINTEGRALHEIGHT | LBS_USETABSTOPS,
- 0, 0, Rect.right, 14, hWnd, (HMENU)8, hInst, NULL );
- if( ! hNew )
- return( FALSE ); // If listbox fails, exit
-
- iSep[ 0 ] = 60; // Add one tab stop
- SendMessage( hNew, LB_SETTABSTOPS, 1, (LPARAM)iSep );
- SendMessage( hNew, LB_ADDSTRING, 0, // Add header text
- (LPARAM)"Process Name\tProcess ID" );
- SendMessage( hNew, LB_SETCURSEL, 0, 0 );
-
- // Now create the process listbox (dig them styles!)
- hNew = CreateWindow( "listbox", NULL, WS_CHILD | WS_BORDER | WS_VISIBLE |
- LBS_NOTIFY | LBS_NOINTEGRALHEIGHT | WS_VSCROLL |
- LBS_USETABSTOPS | WS_TABSTOP,
- 0, 14, Rect.right, ( Rect.bottom / 2 ) - 14,
- hWnd, (HMENU)10, hInst, NULL );
- if( ! hNew )
- return( FALSE ); // Set a tab stop here, too
- SendMessage( hNew, LB_SETTABSTOPS, 1, (LPARAM)iSep );
- // Create heap header listbox
- hNew = CreateWindow( "listbox", NULL, WS_CHILD | WS_BORDER | WS_VISIBLE |
- LBS_NOINTEGRALHEIGHT | LBS_USETABSTOPS,
- 0, ( Rect.bottom / 2 ) + 2,
- Rect.right, 14, hWnd, (HMENU)9, hInst, NULL );
- if( ! hNew )
- return( FALSE );
-
- iSep[ 0 ] = 36; // This needs three tab settings
- iSep[ 1 ] = 66;
- iSep[ 2 ] = 96;
- SendMessage( hNew, LB_SETTABSTOPS, 3, (LPARAM)iSep );
-
- SendMessage( hNew, LB_ADDSTRING, 0, // Set heap header text
- (LPARAM)"Handle\tAddress\tSize\tFlags" );
- SendMessage( hNew, LB_SETCURSEL, 0, 0 );
- // and create the heap listbox
- hNew = CreateWindow( "listbox", NULL, WS_CHILD | WS_BORDER | WS_VISIBLE |
- LBS_NOTIFY | LBS_NOINTEGRALHEIGHT | WS_VSCROLL |
- LBS_USETABSTOPS | WS_TABSTOP,
- 0, ( Rect.bottom / 2 ) + 16,
- Rect.right, ( Rect.bottom / 2 ) - 16,
- hWnd, (HMENU)11, hInst, NULL );
-
- if( ! hNew )
- return( FALSE );
- // Set tabstops here, too
- SendMessage( hNew, LB_SETTABSTOPS, 3, (LPARAM)iSep );
- SetFocus( GetDlgItem( hWnd, 10 ) ); // Process box has focus first
- return( TRUE );
- } // End of CreateChildWindows()
-
- // === Resize Listboxes When Main Window is Resized ===========================
-
- BOOL ResizeChildWindows( HWND hWnd )
- {
- RECT Rect;
- HDWP hDwp;
-
-
- GetClientRect( hWnd, &Rect );
- hDwp = BeginDeferWindowPos( 4 ); // Make it look nice, use this
-
- DeferWindowPos( hDwp, GetDlgItem( hWnd, 8 ), NULL, // Resize header
- 0, 0, Rect.right, 14, SWP_NOZORDER );
-
- DeferWindowPos( hDwp, GetDlgItem( hWnd, 10 ), NULL, // Resize process
- 0, 14, // ID listbox
- Rect.right, ( Rect.bottom / 2 ) - 16,
- SWP_NOZORDER );
-
- DeferWindowPos( hDwp, GetDlgItem( hWnd, 9 ), NULL, // Resize heap header
- 0, ( Rect.bottom / 2 ) + 2,
- Rect.right, 14, SWP_NOZORDER );
-
- DeferWindowPos( hDwp, GetDlgItem( hWnd, 11 ), NULL, // Resize heap listbox
- 0, ( Rect.bottom / 2 ) + 16,
- Rect.right, ( Rect.bottom / 2 ) - 16,
- SWP_NOZORDER );
- EndDeferWindowPos( hDwp ); // Let 'em fly
- return( TRUE );
- } // End of ResizeChildWindows()
-
- // === Display Running Processes in a Listbox =================================
-
- BOOL ListProcesses( HWND hListbox )
- {
- HANDLE hMemShot;
- PROCESSENTRY32 pe;
- BOOL bStatus;
- char szStr[ 256 ];
- int iItem;
-
- // Take a picture of Win32 memory
- hMemShot = CreateToolhelp32Snapshot( TH32CS_SNAPALL, 0 );
- if( ! hMemShot || hMemShot == INVALID_HANDLE_VALUE )
- return( FALSE ); // Bail out if picture failed
-
- SendMessage( hListbox, LB_RESETCONTENT, 0, 0 ); // Clear listbox contents
-
- pe.dwSize = sizeof(PROCESSENTRY32); // Initialize structure
- bStatus = Process32First( hMemShot, &pe ); // Get first process entry
- while( bStatus ) // (at the time of the picture)
- { // Use ID's to find module name
- if( ! FindModuleByID( pe.th32ProcessID, pe.th32ModuleID,
- szStr ) )
- lstrcpy( szStr, "<Unknown>" ); // If no name, mark accordingly
- // Add process ID after name
- wsprintf( szStr + lstrlen( szStr ), "\t%.8lx", pe.th32ProcessID );
- strupr( szStr );
- // Add string to process listbox
- iItem = SendMessage( hListbox, LB_ADDSTRING, 0, (LPARAM)szStr );
- if( iItem != LB_ERR ) // Add process ID as item data
- SendMessage( hListbox, LB_SETITEMDATA, iItem, pe.th32ProcessID );
-
- bStatus = Process32Next( hMemShot, &pe ); // Do it for all processes
- }
-
- CloseHandle( hMemShot ); // Clean up and...
- return( TRUE );
- } // End of ListProcesses()
-
- // === Gets the executable a Process comes from ===============================
-
- BOOL FindModuleByID( DWORD dwProcID, DWORD dwModuleID, char *pszBuffer )
- {
- HANDLE hMemShot;
- MODULEENTRY32 me;
- BOOL bStatus;
-
- // Take a shot of Win32 memory
- hMemShot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwProcID );
- if( ! hMemShot || hMemShot == INVALID_HANDLE_VALUE )
- return( FALSE );
-
- me.dwSize = sizeof(MODULEENTRY32);
- bStatus = Module32First( hMemShot, &me ); // Start looking at modules
- while( bStatus )
- {
- if( me.th32ModuleID == dwModuleID ) // Is this the module we want?
- break; // If so, quit this loop
-
- bStatus = Module32Next( hMemShot, &me ); // If not, try the next one
- }
-
- if( me.th32ModuleID == dwModuleID ) // If this is our module
- lstrcpy( pszBuffer, me.szModule ); // copy it's name
- else
- *pszBuffer = '\0'; // Else, make it a zero length string
-
- CloseHandle( hMemShot ); // Clean up and exit
- return( bStatus );
- } // End of FindModuleByID()
-
- // === Display Process Heap in Listbox ========================================
-
- BOOL ListProcessHeap( HWND hListbox, DWORD dwProcID )
- {
- HANDLE hMemShot;
- HEAPLIST32 hl;
- HEAPENTRY32 he;
- BOOL bStatus, bHeapListStatus;
- char szStr[ 256 ];
- int iItem;
-
- // Take a picture of Win32 memory
- hMemShot = CreateToolhelp32Snapshot( TH32CS_SNAPHEAPLIST, dwProcID );
- if( ! hMemShot || hMemShot == INVALID_HANDLE_VALUE )
- return( FALSE ); // Quit if it fails
-
- SendMessage( hListbox, LB_RESETCONTENT, 0, 0 ); // Clear out the listbox
-
- hl.dwSize = sizeof(HEAPLIST32); // Initialize the list structure
- // and get the first heap list item
- bHeapListStatus = Heap32ListFirst( hMemShot, &hl );
- while( bHeapListStatus ) // This begins the OUTER loop
- {
- he.dwSize = sizeof(HEAPENTRY32); // Initialize the heap entry struct
- // Get first entry of this list
- bStatus = Heap32First( &he, dwProcID, hl.th32HeapID );
- while( bStatus ) // This begins the INNER loop
- {
- wsprintf( szStr, "%.8lx\t%.8lx\t%ld\t", // Display some stats
- he.hHandle, he.dwAddress, he.dwBlockSize );
-
- if( hl.dwFlags & HF32_DEFAULT ) // More stuff to show
- lstrcat( szStr, "Def+" );
- if( hl.dwFlags & HF32_SHARED )
- lstrcat( szStr, "Share+" );
- if( he.dwFlags & LF32_FIXED )
- lstrcat( szStr, "Fix" );
- if( he.dwFlags & LF32_FREE )
- lstrcat( szStr, "Free" );
- if( he.dwFlags & LF32_MOVEABLE )
- lstrcat( szStr, "Move" );
-
- strupr( szStr ); // Add the string to the heap list
- iItem = SendMessage( hListbox, LB_ADDSTRING, 0, (LPARAM)szStr );
- if( iItem != LB_ERR ) // Add process ID as item data
- SendMessage( hListbox, LB_SETITEMDATA, iItem, hl.th32ProcessID );
-
- bStatus = Heap32Next( &he ); // This ends the INNER loop by failing
- } // and this ends the OUTER loop by failing
- bHeapListStatus = Heap32ListNext( hMemShot, &hl );
- }
-
- CloseHandle( hMemShot ); // Clean up and exit
- return( TRUE );
- } // End of ListProcessHeap()
-
- // === Displays Contents of Heap Item =========================================
-
- BOOL WINAPI DataDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
- {
- switch( msg )
- {
- case WM_INITDIALOG: // Current heap selection is in lParam
- {
- char szStr[ 256 ], chVal, *pstr;
- char *szBuffer;
- HANDLE hMem;
- DWORD dwProcessID, dwAddress, dwSize, dwRead;
- int i, j, iRows;
- HFONT hFont;
-
-
- i = 270; // Set a tab stop between HEX and ASCII
- SendDlgItemMessage( hDlg, 100, LB_SETTABSTOPS, 1, (LPARAM)&i );
- // Get line from heap listbox on parent
- SendDlgItemMessage( GetParent( hDlg ), 11, LB_GETTEXT, lParam,
- (LPARAM)szStr );
- // Get item owner process ID
- dwProcessID = SendDlgItemMessage( GetParent( hDlg ), 11,
- LB_GETITEMDATA, lParam, 0 );
- if( ! lstrlen( szStr ) )
- {
- EndDialog( hDlg, TRUE ); // Just in case something goes south
- return( TRUE );
- }
- dwAddress = dwSize = 0;
-
- pstr = strchr( szStr, '\t' ); // Search for tab which signals
- if( pstr )
- {
- ++pstr; // the start of the block address substring
- for( i = 0; i < 8; i++ ) // Loop through 8 hex digits
- {
- chVal = *( pstr + 7 - i ); // Get character from string
- if( chVal > '9' ) // Turn ASCII into 0-15
- chVal -= 55;
- else
- chVal -= 48;
- // Shift into position and add to address
- dwAddress = dwAddress + ( chVal << ( 4 * i ) );
- }
- // When hex is done, search for next tab
- pstr = strchr( pstr, '\t' );
- if( pstr ) // which signals start of size substring
- {
- ++pstr;
- dwSize = atoi( pstr ); // Size is decimal, so runtime works
- }
- }
-
- if( ! dwAddress || ! dwSize ) // Sanity check
- {
- EndDialog( hDlg, TRUE );
- return( TRUE );
- }
-
- if( dwSize > 16384 ) // Don't load more than this for
- dwSize = 16384; // the listbox's sake
-
- hMem = GlobalAlloc( GHND, dwSize + 8 ); // Grab enough buffer
- if( ! hMem )
- {
- EndDialog( hDlg, TRUE );
- return( TRUE );
- }
-
- szBuffer = GlobalLock( hMem );
- // Read memory from specified heap item
- if( Toolhelp32ReadProcessMemory( dwProcessID, (LPVOID)dwAddress,
- szBuffer, dwSize, &dwRead ) )
- {
- iRows = (int)dwSize / 16; // Turn bytes into rows
- if( (int)dwSize % 16 )
- ++iRows; // Add one if there's a remainder for partial line
-
- for( i = 0; i < iRows; i++ ) // Start rows loop
- {
- szStr[ 0 ] = '\0'; // Initialize display line
-
- for( j = 0; j < 16; j++ ) // Loop through line characters
- if( ( i * 16 ) + j < (int)dwSize ) // In range?
- wsprintf( szStr + lstrlen( szStr ), "%.2x ", // Yup, add
- (BYTE)szBuffer[ ( i * 16 ) + j ] ); // to string
-
- strupr( szStr ); // Convery hex numbers to uppercase
- pstr = szStr + lstrlen( szStr );
- *pstr = '\t'; // Append tabstop to hex string
- ++pstr; // Add ASCII after tab
-
- for( j = 0; j < 16; j++ ) // Loop through this line
- if( ( i * 16 ) + j < (int)dwSize )
- { // If it's displayable, add it
- if( szBuffer[ ( i * 16 ) + j ] > ' ' &&
- szBuffer[ ( i * 16 ) + j ] < 'z' )
- *pstr++ = szBuffer[ ( i * 16 ) + j ];
- else
- *pstr++ = '.'; // If not, add a dot instead
- }
-
- *pstr = '\0';
-
- SendDlgItemMessage( hDlg, 100, LB_ADDSTRING, 0, // Add line
- (LPARAM)szStr ); // to listbox
- }
- }
- GlobalUnlock( hMem ); // Free buffer space
- GlobalFree( hMem );
- // Use courier font in the listbox
- hFont = CreateFont( -8, 0, 0, 0, FW_NORMAL, 0, 0, 0, 0, 0, 0, 0, 0,
- "Courier" );
- SendDlgItemMessage( hDlg, 100, WM_SETFONT, (WPARAM)hFont, 1 );
- SetProp( hDlg, MAKEINTATOM( 10000 ), hFont ); // Save font handle
- return( TRUE ); // for closing
- } // End of WM_INITDIALOG
-
-
- case WM_COMMAND:
- if( wParam == IDOK || wParam == IDCANCEL ) // It just closes
- { // Delete the courier font
- DeleteObject( GetProp( hDlg, MAKEINTATOM( 10000 ) ) );
- RemoveProp( hDlg, MAKEINTATOM( 10000 ) ); // Delete the prop
- EndDialog( hDlg, TRUE );
- return( TRUE ); // And that's that
- }
- break;
- }
- return( FALSE );
- } // End of DataDlgProc()
-
- // === Ye Olde About Boxe =====================================================
-
-
- BOOL WINAPI AboutDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
- { // All work and no play makes Jack a dull boy
- switch( msg ) // All work and no play makes Jack a dull boy
- { // All work and no play makes Jack a dull boy
- case WM_INITDIALOG: // All work and no play makes Jack a dull boy
- return( TRUE ); // All work and no play makes Jack a dull boy
- // All work and no play makes Jack a dull boy
- // All work and no play makes Jack a dull boy
- case WM_COMMAND: // All work and no play makes Jack a dull boy
- if( wParam == IDOK || // All work and no play makes Jack a dull boy
- wParam == IDCANCEL )// All work and no play makes Jack a dull boy
- { // All work and no play makes Jack a dull boy
- EndDialog( hDlg, // All work and no play makes Jack a dull boy
- TRUE ); // All work and no play makes Jack a dull boy
- return( TRUE ); // All work and no play makes Jack a dull boy
- } // All work and no play makes Jack a dull boy
- break; // All work and no play makes Jack a dull boy
- } // All work and no play makes Jack a dull boy
- return( FALSE ); // All work and no play makes Jack a dull boy
- } // All work and no play makes Jack a dull boy
-
- // ============================================================================
-